package com.asteros.client;

import java.util.ArrayList;

public class Celda implements Comparable<Celda> {
	
	char color; //g, r, a
	public double posx, posy, centrox, centroy, columna;
	Celda[] vecinos;
	Ficha ficha;
	
	public Celda(char col, double cenx, double ceny, double column){
		color = col;
		centrox = cenx;
		centroy = ceny;
		posx = cenx - 15;
		posy = ceny - 15;
		columna = column;
		vecinos = new Celda[6];
		Asteros.celdas.add(this);
		ficha = null;
	}
	
	public void copiar(char col, double cenx, double ceny, double column){
		color = col;
		centrox = cenx;
		centroy = ceny;
		posx = cenx - 15;
		posy = ceny - 15;
		columna = column;
	}
	
	/**
	 * crea las celdas adyacentes recursivamente 
	 * @param col el número total de columnas a agregar
	 */
	public void crearVecinos(double col){
		Celda aux;
		double x = this.centrox;
		double y = this.centroy;
		double angulo;
		double separacion = 30;
		
		if(this.columna >= col){ 
			int conteo = 0;
			Celda orillas[] = new Celda[6];
				for(int i=0; i<6; i++){
					angulo = i * 60;
					x = this.centrox + separacion * Math.sin(Math.toRadians(angulo));
					y = this.centroy + separacion * Math.cos(Math.toRadians(angulo));
					
					Celda celd = getCelda(x, y);
					if(Asteros.celdas.contains(celd)){
						conteo++;
					}
					orillas[i] = celd;
				}
				//this.vecinos = new Celda[conteo];
				conteo = 0;
				for(Celda c : orillas){
					if(c != null){
						this.vecinos[conteo++] = c; 
					}
				}
				return;
			}

		ArrayList<Celda> faltantes = new ArrayList<Celda>();
		for(int i=0; i<6; i++){
			angulo = i * 60;
			x = this.centrox + separacion * Math.sin(Math.toRadians(angulo));
			y = this.centroy + separacion * Math.cos(Math.toRadians(angulo));
			
			Celda celd = getCelda(x, y);
			if(!Asteros.celdas.contains(celd)){ //que pasa aquí
				aux = new Celda('g', x, y, this.columna + 1);
				faltantes.add(aux);
				this.vecinos[i] = aux;
			}else{
				if(celd.columna > this.columna+1){
				  	celd.copiar('g', x, y, this.columna + 1);//TODO con las imagenes perfectas, quitar linea
					faltantes.add(celd);
				}
				this.vecinos[i] = celd;
			}
		}
		for(Celda c : faltantes){
			c.crearVecinos(col);
		}
	}

	/**
	 * busca una celda por las cordenadas de su centro
	 * @param x 
	 * @param y
	 * @return la celda o null si no esta
	 */
	public static Celda getCelda(double x, double y) {
		final double radio = 14;//TODO calibrar, debe avarcar toda la celda
		for(Celda cel : Asteros.celdas){
			if( Math.abs(cel.centrox - x) < radio &&
				Math.abs(cel.centroy - y) < radio){
				return cel;
			}
		}
		return null;
	}
	
	/**
	 * 0 = abajo y avanza contra reloj
	 * @return
	 */
	public Celda[] getVecinos(){
		if(vecinos.length == 6){
			return vecinos;
		}
		double x = this.centrox;
		double y = this.centroy;
		double angulo;
		double separacion = 30;
		
		Celda orillas[] = new Celda[6];
			for(int i=0; i<6; i++){
				angulo = i * 60;
				x = this.centrox + separacion * Math.sin(Math.toRadians(angulo));
				y = this.centroy + separacion * Math.cos(Math.toRadians(angulo));
				
				Celda celd = Celda.getCelda(x, y);
				orillas[i] = celd;
			}
			return orillas;
	}

	/**
	 * TODO Borrar?
	 * Crea todas las celdas del tablero
	 * @param x
	 * @param y
	 * @param col numero de columnas a graficar
	 */
	public static void tablero(double x, double y, double col) {
		//new Celda('g', x, y, 0).crearVecinos();
		Celda centro = new Celda('g', x, y, 0);
		centro.crearVecinos(col);
		
	}

	@Override
	public int compareTo(Celda cel2) {		
		
		if(this.columna == cel2.columna){
			if(this.anguloCentral() == cel2.anguloCentral()){
				return 0;
			}
			
			if(this.anguloCentral() < cel2.anguloCentral()){
				return -1;
			}else{
				return 1;
			}

		}else{
			return (int) (this.columna - cel2.columna);
		}
	}
	
	//TODO optimizar...
	private double anguloCentral(){
		//pico = el punto más arriba en la circunferencia
		double picox = Asteros.x;
		double picoy = Asteros.y - this.hipotenusa(Asteros.x, Asteros.y);//TODO corregir
		
		
		double res = (this.centrox * picox) + (this.centroy * picoy);// = sen(angulo)
		
		res /= Math.pow(this.hipotenusa(Asteros.x, Asteros.y), 2);
		
		//acos pide valores de -1 a 1
		//res /= 2* this.hipotenusa(Asteros.x, Asteros.y); //TODO corregir
		res /= (Asteros.x * picox) + (Asteros.y + this.hipotenusa(Asteros.x, Asteros.y) * picoy);
		
		if(this.centrox < Asteros.x){
			res *= -1;
		}

		res = Math.acos(res);
		//res = Math.toDegrees(Math.acos(res)); //se saca el arc coseno para tener =angulo
		return res;
	}
	
	//obtiene la distancia de su centro al punto x, y
	private double hipotenusa(double x, double y){
		return Math.sqrt(
				(Math.pow((this.centrox -x), 2)+
				Math.pow((this.centroy -y), 2)));
	}
	
	/**
	 * Revisa si dos celdas son vecinas y en que posición (si es que lo son)
	 * @param c celda a revisar si es vecina
	 * @return -1 si no es vecino o el # de vecino que es
	 */
	public int esVecino(Celda c){
		Celda vecinos[] =c.getVecinos();
		for(int i= 0; i<6; i++){
			if(vecinos[i].equals(c)){
				return i;
			}
		}
		return -1;
	}
	
	public boolean equals(Celda c){
		return this.centrox == c.centrox && this.centroy == c.centroy;
	}
}




















